package com.basker.pisces.domain.entity.iterate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.basker.pisces.domain.entity.meta.AbstractEntity;
import com.basker.pisces.domain.entity.meta.ChildEntity;
import com.basker.pisces.domain.entity.meta.Entity;

public class EntityIterator {
    private Object[] rootDataObjects;
    private Entity rootEntity;
    private IEntityIterateHandler handler;

    public EntityIterator(Entity rootEntity, Object[] rootDataObjects, IEntityIterateHandler handler) {
        this.rootDataObjects = rootDataObjects;
        this.rootEntity = rootEntity;
        this.handler = handler;
    }

    public void iterate() {
        this.iterate(rootEntity, null, Arrays.asList(rootDataObjects));
    }

    private void iterate(AbstractEntity currentEntity, List<Object> parentObjects, List<Object> dataObjects) {
        EntityIterateEvent event = new EntityIterateEvent(currentEntity, parentObjects, dataObjects);
        this.handler.handle(event);

        for (ChildEntity childEntity : currentEntity.getChildEntities()) {
            int totalSize = dataObjects.stream().map(o -> childEntity.getValue(o).size()).reduce(Integer::sum).get();

            List<Object> allChildObjects = new ArrayList<Object>(totalSize);
            List<Object> allParentObjects = new ArrayList<Object>(totalSize);

            for (Object parentObj : dataObjects) {
                List<Object> childObjs = childEntity.getValue(parentObj);
                allChildObjects.addAll(childObjs);

                for (int i = 0; i < childObjs.size(); i++) {
                    allParentObjects.add(parentObj);
                }

                this.iterate(childEntity, allParentObjects, allChildObjects);
            }

        }
    }

}
